/*!
 * Lazy Load - JavaScript plugin for lazy loading images
 *
 * Copyright (c) 2007-2019 Mika Tuupola
 *
 * Licensed under the MIT license:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Original Plugin Source: https://appelsiini.net/projects/lazyload
 * Customize by: https://Gethugothemes.com
 *
 */

(function (root, factory) {
  if (typeof exports === "object") {
    module.exports = factory(root);
  } else if (typeof define === "function" && define.amd) {
    define([], factory);
  } else {
    root.LazyLoad = factory(root);
  }
})(
  typeof global !== "undefined" ? global : this.window || this.global,
  function (root) {
    "use strict";

    if (typeof define === "function" && define.amd) {
      root = window;
    }

    const defaults = {
      src: "data-src",
      srcset: "data-srcset",
      selector: ".lazy",
      root: null,
      rootMargin: "0px",
      threshold: 0.5,
    };

    /**
     * Merge two or more objects. Returns a new object.
     * @private
     * @param {Boolean}  deep     If true, do a deep (or recursive) merge [optional]
     * @param {Object}   objects  The objects to merge together
     * @returns {Object}          Merged values of defaults and options
     */
    const extend = function () {
      let extended = {};
      let deep = false;
      let i = 0;
      let length = arguments.length;

      /* Check if a deep merge */
      if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") {
        deep = arguments[0];
        i++;
      }

      /* Merge the object into the extended object */
      let merge = function (obj) {
        for (let prop in obj) {
          if (Object.prototype.hasOwnProperty.call(obj, prop)) {
            /* If deep merge and property is an object, merge properties */
            if (
              deep &&
              Object.prototype.toString.call(obj[prop]) === "[object Object]"
            ) {
              extended[prop] = extend(true, extended[prop], obj[prop]);
            } else {
              extended[prop] = obj[prop];
            }
          }
        }
      };

      /* Loop through each object and conduct a merge */
      for (; i < length; i++) {
        let obj = arguments[i];
        merge(obj);
      }

      return extended;
    };

    function LazyLoad(images, options) {
      this.settings = extend(defaults, options || {});
      this.images = images || document.querySelectorAll(this.settings.selector);
      this.observer = null;
      this.init();
    }

    LazyLoad.prototype = {
      init: function () {
        /* Without observers load everything and bail out early. */
        if (!root.IntersectionObserver) {
          this.loadImages();
          return;
        }

        let self = this;
        let observerConfig = {
          root: this.settings.root,
          rootMargin: this.settings.rootMargin,
          threshold: [this.settings.threshold],
        };

        this.observer = new IntersectionObserver(function (entries) {
          Array.prototype.forEach.call(entries, function (entry) {
            if (entry.isIntersecting) {
              self.observer.unobserve(entry.target);
              let src = entry.target.getAttribute(self.settings.src);
              let srcset = entry.target.getAttribute(self.settings.srcset);
              if ("img" === entry.target.tagName.toLowerCase()) {
                if (src) {
                  entry.target.src = src;
                }
                if (srcset) {
                  entry.target.srcset = srcset;
                }
              } else {
                var newImage = new Image();
                newImage.src = src;
                newImage.onload = function () {
                  entry.target.style.backgroundImage =
                    "url(" + newImage.src + ")";
                };
              }
            }
          });
        }, observerConfig);

        Array.prototype.forEach.call(this.images, function (image) {
          self.observer.observe(image);
        });
      },

      loadAndDestroy: function () {
        if (!this.settings) {
          return;
        }
        this.loadImages();
        this.destroy();
      },

      loadImages: function () {
        if (!this.settings) {
          return;
        }

        let self = this;
        Array.prototype.forEach.call(this.images, function (image) {
          let src = image.getAttribute(self.settings.src);
          let srcset = image.getAttribute(self.settings.srcset);
          if ("img" === image.tagName.toLowerCase()) {
            if (src) {
              image.src = src;
            }
            if (srcset) {
              image.srcset = srcset;
            }
          } else {
            var newImage = new Image();
            newImage.src = src;
            newImage.onload = function () {
              image.style.backgroundImage = "url(" + newImage.src + ")";
            };
          }
        });
      },

      destroy: function () {
        if (!this.settings) {
          return;
        }
        this.observer.disconnect();
        this.settings = null;
      },
    };

    root.lazyload = function (images, options) {
      return new LazyLoad(images, options);
    };

    if (root.jQuery) {
      const $ = root.jQuery;
      $.fn.lazyload = function (options) {
        options = options || {};
        options.attribute = options.attribute || "data-src";
        new LazyLoad($.makeArray(this), options);
        return this;
      };
    }

    return LazyLoad;
  }
);

lazyload();
